// interpreter should be state less
// remove currentState field, same interpreter could be used across state machines (so that big rule files are loaded once)
function JsonRuleInterpreter() {

    // sample coffee machine rules
    this.rules = {
        "_initState_": "wait",
        "wait": {
            "_events_": {
                "cappucino": {
                    "_state_": "cappucino",
                    "_check_": undefined
                },
                "latte": {
                    "_state_": "latte"
                }
            }
        },
        "cappucino": {
            "_onEnter_": "pour drink",
            "_nextState_": "wait"
        },
        "latte": {
            "_onEnter_": "pour drink",
            "_nextState_": "wait"
        }
    };

    this.currentState = null;
    this.onAction = new Delegate();
    this.onEventHandled = new Delegate();
    this.onEventHandleFailed = new Delegate();
}
JsonRuleInterpreter.prototype.Load = function (ruleFile) {
    var xmlhttp = JsonRuleInterpreter.CreateXHTTPReq();
    xmlhttp.open("GET", ruleFile, false);
    xmlhttp.send();
    this.rules = eval(xmlhttp.responseText);
};
JsonRuleInterpreter.prototype.Process = function (event, args) {

    if (!this.currentState
         || !this.rules[this.currentState]["_events_"]
         || !this.rules[this.currentState]["_events_"][event]) {
        this.onEventHandleFailed.call({ "event": event });
        return false;
    }

    if (this.rules[this.currentState]["_events_"][event]["_check_"]
        && !this.rules[this.currentState]["_events_"][event]["_check_"].call(this, args)) {
        this.onEventHandleFailed.call({ "event": event });
        return false;
    }

    if (this.rules[this.currentState]["_events_"][event]["_state_"])
        this.EnterState(this.rules[this.currentState]["_events_"][event]["_state_"]);

    this.onEventHandled.call({ "event": event });
    return true;
};
JsonRuleInterpreter.prototype.Init = function () {

    if (!this.rules["_initState_"]) this.EnterState(this.rules["_initState_"]);
};
JsonRuleInterpreter.prototype.EnterState = function (state) {

    if (!this.rules[state]) throw "rules does not have the specified state to process: " + state;

    this.currentState = state;

    if (this.rules[state]["_onEnter_"])
        this.onAction.call({ "state": state, "actionMessage": this.rules[state]["_onEnter_"] });

    if (this.rules[state]["_nextState_"])
        this.EnterState(this.rules[state]["_nextState_"]);
};
JsonRuleInterpreter.CreateXHTTPReq = function () {
    var xmlhttp = null;
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest();
    }
    else {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    return xmlhttp;
};